package com.hcc.export.spring;

import com.hcc.export.annotation.Export;
import com.hcc.export.annotation.ExportSupport;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * ExportRequestMappingRegister
 *
 * @author hushengjun
 * @date 2025/4/19
 */
public class ExportEndpointRegistrar {

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

    @PostConstruct
    public void registerExportEndpoint() {
        Map<String, Object> exportControllerMap = applicationContext.getBeansWithAnnotation(ExportSupport.class);
        if (exportControllerMap.isEmpty()) {
            return;
        }
        
        for (Map.Entry<String, Object> entry : exportControllerMap.entrySet()) {
            String beanName = entry.getKey();
            Object bean = entry.getValue();
            Class<?> targetClass = AopUtils.getTargetClass(bean);
            Controller controllerAnnotation = AnnotatedElementUtils.findMergedAnnotation(targetClass, Controller.class);
//            RestController restControllerAnnotation = targetClass.getDeclaredAnnotation(RestController.class);
//            Controller controllerAnnotation = targetClass.getDeclaredAnnotation(Controller.class);
            if (controllerAnnotation == null) {
                continue;
            }

            Method[] declaredMethods = targetClass.getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                Export exportAnnotation = declaredMethod.getDeclaredAnnotation(Export.class);
                if (exportAnnotation == null) {
                    continue;
                }

                this.register(bean, declaredMethod, exportAnnotation);
            }
        }
    }

    private void register(Object controller, Method originalMethod, Export exportAnnotation) {
        RequestMapping requestMappingAnnotation = AnnotatedElementUtils.findMergedAnnotation(originalMethod, RequestMapping.class);
        if (requestMappingAnnotation == null) {
            return;
        }

        Class<?> targetClass = AopUtils.getTargetClass(controller);
        RequestMapping requestMappingAnnotationForController = AnnotatedElementUtils.findMergedAnnotation(targetClass, RequestMapping.class);

        String exportPath = this.getExportPath(exportAnnotation, requestMappingAnnotationForController, requestMappingAnnotation);

        // 创建导出RequestMappingInfo
        RequestMappingInfo exportMapping = RequestMappingInfo
                .paths(exportPath)
                .methods(requestMappingAnnotation.method())
                .produces(MediaType.APPLICATION_JSON_VALUE)
                .build();

        // 注册到Spring MVC
        requestMappingHandlerMapping.registerMapping(exportMapping, controller, originalMethod);
    }

    private String getExportPath(Export exportAnnotation, RequestMapping requestMappingAnnotationForController, RequestMapping requestMappingAnnotation) {
        String controllerPath = "";
        if (requestMappingAnnotationForController != null) {
            String[] path = requestMappingAnnotationForController.path();
            if (path.length > 0) {
                controllerPath = path[0];
                if (controllerPath.endsWith("/")) {
                    controllerPath = controllerPath.substring(0, controllerPath.length() - 1);
                }
            }
        }
        String[] paths = requestMappingAnnotation.path();
        String methodPath = paths[0];
        if (!methodPath.startsWith("/")) {
            methodPath = "/" + methodPath;
        }
        if (methodPath.endsWith("/")) {
            methodPath = methodPath.substring(0, methodPath.length() - 1);
        }

        // 创建导出路径
        return controllerPath + methodPath + exportAnnotation.pathSuffix();
    }

}
